/**
 * @file    inf_fan.c
 * @author  yhy
 * @brief   风扇系统源文件
 * @version 1.00
 * @date    2025-08-05
 *
 * @copyright Copyright (c) 2025
 *
 */
#include "inf_fan.h"

#include "drv_gpio.h"
#include "drv_pwm.h"

#include <string.h>

#define FANL_PWM_INSTANCE PWM_INSTANCE_IPWM1
#define FANL_PWM_CHANNEL  PWM_CHANNEL_1
#define FANL_PWM_PIN_NUM  GET_PIN_NUM(D, 2)

#define FANR_PWM_INSTANCE PWM_INSTANCE_SPWM1
#define FANR_PWM_CHANNEL  PWM_CHANNEL_2
#define FANR_PWM_PIN_NUM  GET_PIN_NUM(D, 4)

static result_e inf_fan_pwm_config(void);

/* 风扇系统实例 */
static fan_system_t fan_system;

/**
 * @brief 初始化风扇系统
 *
 * @return result_e 初始化结果, RESULT_STATUS_OK表示成功, 其他值表示失败
 */
result_e inf_fan_init(void)
{
    result_e result = inf_fan_pwm_config();
    if (result != RESULT_STATUS_OK) {
        return result;
    }

    memset(&fan_system, 0, sizeof(fan_system_t));

    fan_system.fans[FAN_IDX_FANL].pwm_config.instance = FANL_PWM_INSTANCE;
    fan_system.fans[FAN_IDX_FANL].pwm_config.pwm_ch   = FANL_PWM_CHANNEL;
    fan_system.fans[FAN_IDX_FANL].gear                = FAN_GEAR_CLOSE;
    fan_system.fans[FAN_IDX_FANL].last_gear           = FAN_GEAR_CLOSE;
    fan_system.fans[FAN_IDX_FANL].fault               = FAN_FAULT_NONE;
    fan_system.fans[FAN_IDX_FANL].blocked             = false;

    fan_system.fans[FAN_IDX_FANR].pwm_config.instance = FANR_PWM_INSTANCE;
    fan_system.fans[FAN_IDX_FANR].pwm_config.pwm_ch   = FANR_PWM_CHANNEL;
    fan_system.fans[FAN_IDX_FANR].gear                = FAN_GEAR_CLOSE;
    fan_system.fans[FAN_IDX_FANR].last_gear           = FAN_GEAR_CLOSE;
    fan_system.fans[FAN_IDX_FANR].fault               = FAN_FAULT_NONE;
    fan_system.fans[FAN_IDX_FANR].blocked             = false;

    fan_system.system_enable = false;

    /* 初始化风扇PWM */
    snf_drv_pwm_set_duty(FANL_PWM_INSTANCE, FANL_PWM_CHANNEL, FAN_GEAR_CLOSE);
    snf_drv_pwm_set_duty(FANR_PWM_INSTANCE, FANR_PWM_CHANNEL, FAN_GEAR_CLOSE);

    return result;
}

/**
 * @brief 设置风扇系统使能状态
 *
 * @param   enable      使能状态
 * @return  result_e    设置结果, RESULT_STATUS_OK表示成功, 其他值表示失败
 */
void inf_fan_set_system_enable(bool enable)
{
    fan_system.system_enable = enable;

    /* 如果是关闭系统, 失能所有的风扇 */
    if (!enable) {
        for (uint8_t i = 0; i < FAN_IDX_MAX; ++i) {
            fan_system.fans[i].gear    = FAN_GEAR_CLOSE;
            fan_system.fans[i].blocked = false;
            fan_system.fans[i].fault   = FAN_FAULT_NONE;
        }
    }
}

/**
 * @brief 设置风扇档位
 *
 * @param   idx         风扇索引
 * @param   gear        档位
 * @return  result_e    设置结果, RESULT_STATUS_OK表示成功, 其他值表示失败
 */
result_e inf_fan_set_gear(fan_idx_e idx, fan_gear_e gear)
{
    if (idx >= FAN_IDX_MAX || gear >= FAN_GEAR_MAX) {
        return RESULT_STATUS_INVALID_PARAM;
    }

    /* 系统使能检查 */
    if (!fan_system.system_enable && gear != FAN_GEAR_CLOSE) {
        return RESULT_STATUS_NOT_INITIALIZED;
    }

    fan_system.fans[idx].gear = gear;

    return RESULT_STATUS_OK;
}

/**
 * @brief 设置风扇故障状态
 *
 * @param   idx         风扇索引
 * @param   fault       故障状态
 * @return  result_e    设置结果, RESULT_STATUS_OK表示成功, 其他值表示失败
 */
result_e inf_fan_set_fault(fan_idx_e idx, fan_fault_e fault)
{
    if (idx >= FAN_IDX_MAX || fault >= FAN_FAULT_MAX) {
        return RESULT_STATUS_INVALID_PARAM;
    }

    fan_system.fans[idx].fault = fault;

    return RESULT_STATUS_OK;
}

/**
 * @brief 检查风扇互锁状态
 *
 * @param idx       风扇索引
 * @param blocked   互锁状态
 * @return result_e 检查结果, RESULT_STATUS_OK表示成功, 其他值表示失败
 */
result_e inf_fan_check_interlock(fan_idx_e idx, bool blocked)
{
    if (idx >= FAN_IDX_MAX) {
        return RESULT_STATUS_INVALID_PARAM;
    }

    /* 如果加热系统激活, 并且风扇不是关闭状态, 则设置阻塞 */
    if (blocked && fan_system.system_enable && fan_system.fans[idx].gear != FAN_GEAR_CLOSE) {
        fan_system.fans[idx].gear = FAN_GEAR_CLOSE;
    }

    fan_system.fans[idx].blocked = blocked;

    return RESULT_STATUS_OK;
}

/**
 * @brief 获取风扇档位
 *
 * @param   idx         风扇索引
 * @return  fan_gear_e  档位
 */
fan_gear_e inf_fan_get_gear(fan_idx_e idx)
{
    if (idx >= FAN_IDX_MAX) {
        return FAN_GEAR_MAX;
    }

    return fan_system.fans[idx].gear;
}

/**
 * @brief 获取风扇故障状态
 *
 * @param   idx         风扇索引
 * @return  fan_fault_e 故障状态
 */
fan_fault_e inf_fan_get_fault(fan_idx_e idx)
{
    if (idx >= FAN_IDX_MAX) {
        return FAN_FAULT_MAX;
    }

    return fan_system.fans[idx].fault;
}

/**
 * @brief 获取风扇互锁状态
 *
 * @param   idx         风扇索引
 * @return  true        互锁状态为阻塞
 * @return  false       互锁状态为非阻塞
 */
bool inf_fan_get_bolcked_status(fan_idx_e idx)
{
    if (idx >= FAN_IDX_MAX) {
        return false;
    }

    return fan_system.fans[idx].blocked;
}

/**
 * @brief 风扇系统处理函数，需要在调度器中调度, 50～100ms调度一次
 *
 */
void inf_fan_handle(void)
{
    if (!fan_system.system_enable) {
        return;
    }

    for (uint8_t i = 0; i < FAN_IDX_MAX; ++i) {
        fan_t     *fan      = &fan_system.fans[i];
        fan_gear_e new_gear = fan->gear;

        /* 检查互锁状态 */
        if (fan->blocked && fan->gear != FAN_GEAR_CLOSE) {
            new_gear = FAN_GEAR_CLOSE;
        }

        /* 检查故障状态 */
        if (fan->fault != FAN_FAULT_NONE && fan->gear != FAN_GEAR_CLOSE) {
            new_gear = FAN_GEAR_CLOSE;
        }

        /* 更新PWM输出 */
        if (new_gear != fan->last_gear) {
            snf_drv_pwm_set_duty((snf_pwm_instance_e)fan->pwm_config.instance,
                                 (snf_pwm_channel_e)fan->pwm_config.pwm_ch, new_gear);
            fan->last_gear = new_gear;
        }

        fan->gear = new_gear;
    }
}

/**
 * @brief 初始化风扇PWM
 *
 * @return result_e 初始化结果, RESULT_STATUS_OK表示成功, 其他值表示失败
 */
static result_e inf_fan_pwm_config(void)
{
    snf_pwm_config_t fanl_pwm_config = {
        .instance     = FANL_PWM_INSTANCE,
        .channel_list = { FANL_PWM_CHANNEL },
        .channel_num  = 1,
        .freq         = PWM_FREQ_100HZ,
        .pin_num_list = { FANL_PWM_PIN_NUM },
    };
    result_e result = snf_drv_pwm_init(&fanl_pwm_config);
    if (result != RESULT_STATUS_OK) {
        return result;
    }

    snf_pwm_config_t fanr_pwm_config = {
        .instance     = FANR_PWM_INSTANCE,
        .channel_list = { FANR_PWM_CHANNEL },
        .channel_num  = 1,
        .freq         = PWM_FREQ_100HZ,
        .pin_num_list = { FANR_PWM_PIN_NUM },
    };
    result = snf_drv_pwm_init(&fanr_pwm_config);
    if (result != RESULT_STATUS_OK) {
        return result;
    }

    return RESULT_STATUS_OK;
}
